import unittest, shutil

from timacs.databases.physical_topology import PhysicalTopologyDatabase
from timacs.interfaces.physical_topology import Cluster, Rack, Host


# Constants
TEST_CLUSTER_NAME = "test_cluster_name"
TEST_RACK_NAME = "test_rack_name"
TEST_HOST_NAME = "test_host_name"


class PhysicalTopologyDatabaseTest(unittest.TestCase):
    def setUp( self ):
        self.db = PhysicalTopologyDatabase( "physical_topology_database_test" )
    
    def tearDown( self ):
        self.db = None
        shutil.rmtree( "physical_topology_database_test" )


class PhysicalTopologyDatabaseAddClusterTest(PhysicalTopologyDatabaseTest):
    def runTest( self ):
        self.db.addCluster( Cluster( name=TEST_CLUSTER_NAME ) )


class PhysicalTopologyDatabaseAddRackTest(PhysicalTopologyDatabaseTest):
    def runTest( self ):
        self.db.addCluster( Cluster( name=TEST_CLUSTER_NAME ) )
        self.db.addRack( TEST_CLUSTER_NAME, Rack( name=TEST_RACK_NAME ) )
        
        try:
            self.db.addRack( "other_cluster_name", Rack( name=TEST_RACK_NAME ) )
        except AssertionError:
            raise
        except:
            pass


class PhysicalTopologyDatabaseAddHostTest(PhysicalTopologyDatabaseTest):
    def runTest( self ):
        self.db.addCluster( Cluster( name=TEST_CLUSTER_NAME ) )
        self.db.addRack( TEST_CLUSTER_NAME, Rack( name=TEST_RACK_NAME ) )
        self.db.addHost( TEST_CLUSTER_NAME, TEST_RACK_NAME, Host( name=TEST_HOST_NAME ) )
        
        try:
            self.db.addHost( TEST_CLUSTER_NAME, "other_rack_name", Host( name=TEST_HOST_NAME ) )
        except AssertionError:
            raise
        except: 
            pass


class PhysicalTopologyDatabaseGetClustersTest(PhysicalTopologyDatabaseTest):
    def runTest( self ):
        self.db.addCluster( Cluster( name=TEST_CLUSTER_NAME ) )
        clusters = self.db.getClusters()
        assert len( clusters ) == 1
        assert TEST_CLUSTER_NAME in clusters
        assert clusters[TEST_CLUSTER_NAME].name == TEST_CLUSTER_NAME
        
        
class PhysicalTopologyDatabaseGetRacksByClusterNameTest(PhysicalTopologyDatabaseTest):
    def runTest( self ):
        self.db.addCluster( Cluster( name=TEST_CLUSTER_NAME ) )
        self.db.addRack( TEST_CLUSTER_NAME, Rack( name=TEST_RACK_NAME ) )
        racks = self.db.getRacksByClusterName( TEST_CLUSTER_NAME )
        assert len( racks ) == 1
        assert TEST_RACK_NAME in racks
        assert racks[TEST_RACK_NAME].name == TEST_RACK_NAME

        try: 
            racks = self.db.getRacksByClusterName( "other_cluster_name" )
            self.fail()
        except AssertionError:
            raise
        except:
            pass
        

class PhysicalTopologyDatabaseGetHostsByRackNameTest(PhysicalTopologyDatabaseTest):
    def runTest( self ):
        self.db.addCluster( Cluster( name=TEST_CLUSTER_NAME ) )
        self.db.addRack( TEST_CLUSTER_NAME, Rack( name=TEST_RACK_NAME ) )
        self.db.addHost( TEST_CLUSTER_NAME, TEST_RACK_NAME, Host( name=TEST_HOST_NAME ) )
        hosts = self.db.getHostsByRackName( TEST_RACK_NAME )
        assert len( hosts ) == 1
        assert TEST_HOST_NAME in hosts
        assert hosts[TEST_HOST_NAME].name == TEST_HOST_NAME

        try:
            hosts = self.db.getHostsByRackName( "other_rack_name" )
            self.fail()
        except AssertionError:
            raise
        except:
            pass
            

suite = unittest.TestSuite()
suite.addTest( PhysicalTopologyDatabaseAddClusterTest() )
suite.addTest( PhysicalTopologyDatabaseAddRackTest() )
suite.addTest( PhysicalTopologyDatabaseAddHostTest() )
suite.addTest( PhysicalTopologyDatabaseGetClustersTest() )
suite.addTest( PhysicalTopologyDatabaseGetRacksByClusterNameTest() )
suite.addTest( PhysicalTopologyDatabaseGetHostsByRackNameTest() ) 
